<div id="sources" class="section-profile">
  <div class="advanced row">
      <div class="topleft duk-icon"><img onclick="removeSection('sources')" src="/gui/img/x.png"></div>
      <div class="bottomright duk-icon"><img onclick="toggleSidebar('sources-sidebar')" src="/gui/img/expand.png"></div>
      <div id="sources-sidebar"  class="column section-border" style="flex:25%">
      <img src="/gui/img/facts.png">
      <h4>Sources</h4>
      <br>
      <div class="toggle">
        <label class="switch"><input type="checkbox" id="togBtnSrc" onchange="toggleSourceView()">
          <div class="slider round"><span class="on">ADD</span><span class="off">VIEW</span></div>
        </label>
      </div>
      <br>
      <p class="section-description">
          Facts are identifiable pieces of data, collected by agents or loaded when the server starts.
          A source is a collection of facts. Rules are boundaries to ensure specific traits cannot be used.
      </p>
      <br>
      <div id="viewSource">
          <select id="profile-source-name" style="margin-top:-15px" onchange="loadSource();">
            <option value="" disabled selected>Select an existing source</option>
            {% for s in sources %}
                <option value="{{ s.id }}">{{ s.name }}</option>
            {% endfor %}}
          </select>
      </div>
      <div id="addSource"></div>
      <button id="sourceBtn" type="button" class="button-success atomic-button"
              onclick="viewRules()">View rules
      </button>
      <button id="relationshipBtn" type="button" class="button-success atomic-button"
              onclick="viewRelationships()">View Relationships</button>
      <button id="saveSourceBtn" type="button" class="button-success atomic-button"
              onclick="saveSource()">Save
      </button>
    </div>
    <div class="column adversary-header" style="flex:75%;overflow:hidden;text-align:left">
        <h4 id="source-name" contenteditable="true" class="advGoal">Sample name</h4>
        <hr>
        <table id="factTbl" class="obfuscation-table" border=1 frame=void rules=rows>
            <thead>
                <tr>
                    <th><b>trait</b></th>
                    <th><b>value</b></th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
            </tbody>
        </table>
        <p style="color:white;text-align:right;font-size:16px;" onclick="addFactRow('Enter trait', 'Enter value')">
            &#10010;&nbsp;add fact
        </p>
    </div>
  </div>
</div>

<div id="rule-modal" class="modal source-modal">
    <form class="modal-content">
        <div class="container">
            <div class="row ability-viewer">
                <span onclick="document.getElementById('rule-modal').style.display='none'" class="close" title="Close Modal">&times;</span>
                <div class="column" style="flex:100%">
                    <h3 id="rules-name"></h3>
                    <span>Rules</span>
                    <ul id="source-rules"></ul>
                    <p onclick="addRuleBlock()">&#10010;&nbsp;add rule</p>
                    <p class="source-note">* Rules run in top-down order, in the same way as iptables</p>
                </div>
            </div>
        </div>
    </form>
</div>

<div id="relationship-modal" class="modal source-modal">
    <form class="modal-content">
        <div class="container">
            <div class="row ability-viewer">
                <span onclick="document.getElementById('relationship-modal').style.display='none'" class="close" title="Close Modal">&times;</span>
                <div class="column" style="flex:100%">
                    <h3 id="relationship-name"></h3>
                    <span>Relationships</span>
                    <ul id="source-relationships"></ul>
                    <p onclick="addRelationshipBlock()">&#10010;&nbsp;add relationship</p>
                </div>
            </div>
        </div>
    </form>
</div>

<li id="rule-template" class="row-simple ttp-template source-row" style="display: none;">
    <table>
        <tr>
            <td><b>trait:</b></td>
            <td><input id="trait" contenteditable="false" spellcheck="false"></td>
            <td><p onclick="$(this).closest('li').remove()">&#x274C;</p></td>
        </tr>
        <tr>
            <td><b>match:</b></td>
            <td><input id="match" contenteditable="false" spellcheck="false"></td>
            <td></td>
        </tr>
        <tr>
            <td><b>action:</b></td>
            <td><input id="action" contenteditable="false" spellcheck="false"></td>
            <td></td>
        </tr>
    </table>
</li>

<li id="relationship-template" class="row-simple ttp-template source-row" style="display: none;">
    <table>
        <tr>
            <td><b>source:</b></td>
            <td><input id="sourceTrait" contenteditable="false" spellcheck="false" placeholder="trait"></td>
            <td><input id="sourceValue" contenteditable="false" spellcheck="false" placeholder="value"></td>
            <td><p onclick="$(this).closest('li').remove()">&#x274C;</p></td>
        </tr>
        <tr>
            <td><b>edge:</b></td>
            <td><input id="edge" contenteditable="false" spellcheck="false" placeholder="edge"></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td><b>target:</b></td>
            <td><input id="targetTrait" contenteditable="false" spellcheck="false" placeholder="trait"></td>
            <td><input id="targetValue" contenteditable="false" spellcheck="false" placeholder="value"></td>
            <td></td>
        </tr>
    </table>
</li>

<script>
    $(document).ready(function () {
        stream('New sources will be created after each operation, containing the intelligence that was learned.')
    });
    let refresher = setInterval(refresh, 15000);
    $('.section-profile').bind('destroyed', function() {
        console.log('sources refresh off');
        clearInterval(refresher);
    });

    function refresh(){
        function sourceCallback(data){
            data.forEach(function(s) {
                let found = false;
                $("#profile-source-name > option").each(function() {
                    if($(this).val() === s.id) {
                        found = true;
                    }
                });
                if(!found){
                    $('#profile-source-name').append('<option value="'+s.id+'">'+s.name+'</option>');
                }
            });
        }
        restRequest('POST', {'index':'sources'}, sourceCallback, '/api/rest');
    }

    function toggleSourceView() {
        $('#viewSource').toggle();
        $('#addSource').toggle();
        clearFactCanvas();
    }

    function clearFactCanvas(){
        $('#factTbl tbody tr').remove();
        $('#source-rules').empty();
        $('#source-relationships').empty();
        if($('#source-name').data('id')){
            $('#source-name').data('id', null);
        }
    }

    function loadSource() {
        function loadSourceCallback(data) {
            clearFactCanvas();
            let source = $('#source-name');
            data[0].facts.forEach(f => {
                addFactRow(f.trait, f.value);
            });
            source.data('id', data[0].id);
            applyRules(data[0].rules);
            source.html(data[0].name);
            populateRelationships(data[0].relationships);
        }
        stream('Traits can be used inside ability commands as variables, which get replaced at runtime with their corresponding values.');
        restRequest('POST', {'index':'sources', 'id': $('#profile-source-name').val()}, loadSourceCallback);
    }

    function addFactRow(trait, value){
        $('#factTbl tbody').append(
            '<tr>' +
                '<td><p contenteditable="true">' + trait + '</p></td>' +
                '<td><p contenteditable="true">' + value + '</p></td>' +
                '<td><p onclick="$(this).closest(\'tr\').remove()">&#x274C;</p></td>'+
            '</tr>'
        )
    }

    function saveSource(){
        function saveSourceCallback(data) {
            stream('New fact source saved!');
        }
        let source = $('#source-name');
        let name = source.text();
        let id = source.data('id');
        if(!name){ warn('Please enter a name!'); return; }
        if(!id) {
            id = uuidv4();
            source.data('id', id);
        }
        let data = {};
        data['index'] = 'sources';
        data['id'] = id;
        data['name'] = name;
        data['facts'] = [];
        data['rules'] = [];
        data['relationships'] = []

        $('#factTbl tbody tr').each(function () {
            let trait = $(this.cells[0]).text();
            let value = $(this.cells[1]).text();
            data['facts'].push({'trait':trait,'value':value});
        });

        let invalidRules = 0;
        $('#source-rules li').each(function() {
            let trait = $(this).find('#trait').val();
            let match = $(this).find('#match').val();
            let action = $(this).find('#action').val();
            if(trait === undefined || match === undefined || action === undefined){
                return;
            }
            if(action !== 'ALLOW' && action !== 'DENY') {
                invalidRules += 1;
            }
            data['rules'].push({'trait': trait, 'match': match, 'action': action});
        });
        if(invalidRules > 0) {
            warn(invalidRules + ' invalid rules! Action must be either ALLOW or DENY.');
            return;
        }
        if(data['facts'].length === 0 && data['rules'].length === 0) { warn('Sources must have at least one rule or one fact specified'); return; }
        $('#source-relationships li').each(function() {
            let sourceTrait = $(this).find('#sourceTrait').val();
            let sourceValue = $(this).find('#sourceValue').val();
            let edge = $(this).find('#edge').val();
            let targetTrait = $(this).find('#targetTrait').val();
            let targetValue = $(this).find('#targetValue').val();
            if(sourceTrait === undefined || sourceValue === undefined || edge === undefined || targetTrait == undefined || targetValue == undefined){
                return;
            }
            data['relationships'].push({'source': {'trait':sourceTrait,'value':sourceValue}, 'edge': edge, 'target': {'trait':targetTrait,'value':targetValue}});
        });
        if(data['relationships'].length > 0 && data['facts'].length === 0) { warn('Relationships require at least one fact to be specified.'); return; }
        restRequest('PUT', data, saveSourceCallback);
    }

    function viewRules(){
        document.getElementById("rule-modal").style.display = "block";
        let sourceName = $('#source-name').text();
        $('#rules-name').text(sourceName);
    }

    function applyRules(rules){
        rules.forEach(r => {
            let template = $("#rule-template").clone();
            template.removeAttr('id');
            template.find('#trait').val(r.trait);
            template.find('#match').val(r.match);
            if(r.action === 0) {
                template.find('#action').val('DENY');
            } else if (r.action === 1) {
                template.find('#action').val('ALLOW');
            }
            template.show();
            $('#source-rules').append(template);
        });
    }

    function addRuleBlock(){
        let template = $("#rule-template").clone();
        template.removeAttr('id');
        template.show();
        $('#source-rules').append(template);
    }

    function populateRelationships(relationships){
        relationships.forEach(r => {
            let template = $("#relationship-template").clone();
            template.removeAttr('id');
            template.find('#sourceTrait').val(r.source.trait);
            template.find('#sourceValue').val(r.source.value);
            template.find('#edge').val(r.edge);
            template.find('#targetTrait').val(r.target.trait);
            template.find('#targetValue').val(r.target.value);
            template.show();
            $('#source-relationships').append(template);
        });
    }

    function viewRelationships(){
        document.getElementById("relationship-modal").style.display = "block";
        let sourceName = $('#source-name').text();
        $('#relationship-name').text(sourceName);
    }

    function addRelationshipBlock(){
        let template = $("#relationship-template").clone();
        template.removeAttr('id');
        template.show();
        $('#source-relationships').append(template);
    }

    //# sourceURL=sources.js
</script>
